import 'dart:io';
import 'dart:math';

void main()
{
//   var name='Voyoger I';
//   print(name);
//    print('Hello, World!');

//    var year=2008;

//    var antennaDiameter=3.7;
//    var flyObjects=['Jupiter','Saturn','Uranus','Neptune'];

//    var image ={
//     'tags':['saturn'],
//     'url':'//path/to/saturn.png'
//    };

//    for(final object in flyObjects){
//     print(object);
//    }

//    for(int month=1;month <= 12; month++){
//     print(month);
//    }

//    while(year < 2024){
//     year +=1;
//    }


//    if (year >= 2001) {
//   print('21st century');
// } else if (year >= 1901) {
//   print('20th century');
// }


//  var result =fibonacci(20);

//  flyObjects.where((name) => name.contains('turn')).forEach(print);


// }


// int fibonacci(int n){
//   if (n == 0|| n == 1) return n;
//   return fibonacci(n-1)+fibonacci(n-2);


var listOfInts=[1,2,3];

var  listOfStrings=[' #0',for(var i in listOfInts) '#$i'];

print(listOfStrings);

printWithDelay(listOfStrings.toString());

print('hello end');

}

const oneSecond = Duration(seconds: 10);

Future<void> printWithDelay(String message) async {
  await Future.delayed(oneSecond);
  print(message);
}


Future<void> printWithDelay2(String message){
  
  return Future.delayed(oneSecond).then(
    (_) {
      print(message);
    }
  );
}




Future<void> createDescriptions(Iterable<String> objects) async {
   for(final object in objects){
    try{
       var file =File('$objects.txt');
       if(await file.exists()){
        var modified = await file.lastModified();
        print('File for $object already exists. It was modified on $modified.');
        continue;
       }
       await file.create();
       await file.writeAsString('Start describing $object in this file. ');
    } on IOException catch (e){
      print('Cannot create description for $object: $e');
    }

   }  
}


Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {

  for(final object in objects){
    await Future.delayed(oneSecond);
    yield '${craft.name} flies by $object';
  }
}



typedef IntList=List<int>;

typedef ListMapper<X> = Map<X,List<X>>;




enum PlanetType {terrestrial, gas, ice}

enum Planet{
  mercury(planetType:PlanetType.terrestrial,moons:0, hasRings:false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  uranus(planetType: PlanetType.ice,moons: 27,hasRings: true),
  neptune(planetType: PlanetType.ice, moons: 14, hasRings: true);



  /// A constant generating constructor
   const Planet(
    {required this.planetType, required this.moons, required this.hasRings});


   //All instance variables are final 
    final PlanetType planetType;
    final int moons;
    final bool hasRings;

    ///Enhanced enums support getters and other method
    
    bool get isGiant => 
         planetType == PlanetType.gas || planetType ==PlanetType.ice;

}


class Spacecraft{
  String name;
  DateTime? launchDate;

  //Readonly non-final property

  int? get launchYear => launchDate?.year;

   //Constructor, with syntoctic sugar for assignment to members.

   Spacecraft(this.name, this.launchDate){
    //Initialization code goes here.
   }

   //Named constructor that forwards to the default one.

   Spacecraft.unlaunched(String name):this(name,null);


   //Method.

   void describe(){

    print('Spacecraft: $name');
    //Type promotion doesn't work on getters.
    var launchDate = this.launchDate;
    if(launchDate != null){
      int years = DateTime.now().difference(launchDate).inDays ~/ 365;
      print('Launched: $launchYear($years years ago)');
    }
    else {
      print('Unlaunched');
    }
   }


}


class Orbiter extends Spacecraft{
  double altitude;
  Orbiter(super.name,DateTime super.launchDate,this.altitude);

}

abstract class Describable{
  void describe();

  void describeWithEmphasis(){
    print('===================');
    describe();
    print('===================');

  }
}
